package controlador;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.EventObject;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;

import org.hibernate.criterion.Restrictions;

import dao.imp.Base_DatosDAO;

import vista.frmGestionarPago;
import modelo.Cliente;
import modelo.Cuenta;
import modelo.Empresa;
import modelo.Pago;
import modelo.Tipo_Pago;

public class ControladorGestionarPago {
	private static final String DESCUENTO = "DESCUENTO";
	private Empresa empresa;
	private frmGestionarPago frmpago;
	private Cliente cliente = null;
	
	public ControladorGestionarPago(Cliente cliente) {
		init();
		cargarCliente(cliente);
	}
	
	private void init(){
		this.frmpago = new frmGestionarPago(this);
		this.frmpago.setLocationRelativeTo(null);
		this.frmpago.setVisible(true);
		Base_DatosDAO conexion = new Base_DatosDAO();
		this.empresa = (Empresa)conexion.findByProperty(Empresa.class, Restrictions.eq("estatus", 'a')).get(0);
		cargarTiposPagos();
	}
	
	public ControladorGestionarPago() {
		init();
	}

	private void cargarTiposPagos() {
		List<Tipo_Pago> tipos = empresa.getTipos_Pago();
		for (int i=0;i<tipos.size();i++){
			this.frmpago.getCmbtipopago().addItem(tipos.get(i).getNombre());
		}
	}

	private void cargarCliente(Cliente cliente) {
		cancelar();
		this.frmpago.getCmbidentificacion().setSelectedItem(cliente.getCedula_rif().subSequence(0, 2));
		this.frmpago.getLblapellido2().setText(cliente.getApellido());
		this.frmpago.getTxtnumero().setText(cliente.getCedula_rif().substring(2));
		this.frmpago.getLblnombre2().setText(cliente.getNombre());
		this.frmpago.getCmbidentificacion().setEnabled(false);
		this.frmpago.getTxtnumero().setEnabled(false);
		actualizarMontosDeuda(cliente);
		cargarCuentas(cliente);
		this.cliente = cliente;
		this.frmpago.getCmbtipopago().setEnabled(true);
		this.frmpago.getCmbcuenta_pagar().setEnabled(true);
	}

	private void cargarCuentas(Cliente cliente) {
		List<Cuenta> cuentas;
		try {
			cuentas = empresa.Buscar_Cuentas_NoCerradas_Cliente(cliente);
			int size = cuentas.size();
			this.frmpago.getCmbcuenta_pagar().addItem("Seleccione Cuenta a Pagar");
			for (int i=0;i<size;i++){
				Cuenta cuenta = cuentas.get(i);
				String fecha = String.valueOf(cuentas.get(i).getFecha().toGMTString().substring(2, 6).replaceAll(" ", "")+"-"+cuentas.get(i).getFecha().toGMTString().substring(6, 11)).replaceAll(" ", "");
				this.frmpago.getCmbcuenta_pagar().addItem(fecha+" Saldo: "+cuenta.Calcular_Saldo()+" Bs");
			}
		} catch (ParseException e1) {
			e1.printStackTrace();
		}
	}

	private void actualizarMontosDeuda(Cliente cliente) {
		if (cliente==null){
			this.frmpago.getLblmontodeuda().setText("0.0 Bsf");
			this.frmpago.getLblmontodeuda_delcliente().setText("0.0 Bsf");
		}else {
			try {
				double deuda_cliente=0,deuda_delcliente=0;
				List<Cuenta> cuentas = empresa.Buscar_Cuentas_NoCerradas_Cliente(cliente);
				int size = cuentas.size();
				double monto;
				for (int i=0;i<size;i++){
					monto = cuentas.get(i).Calcular_Saldo();
					if (monto<0){
						deuda_delcliente+=monto;
					}else{
						deuda_cliente+=monto;
					}
				}
				this.frmpago.getLblmontodeuda_delcliente().setText(String.valueOf(deuda_delcliente)+" Bsf");
				this.frmpago.getLblmontodeuda().setText(String.valueOf(deuda_cliente)+" Bsf");
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
	}

	public void procesarEvento(EventObject evento){
		if (evento.getClass().equals(ActionEvent.class)){
			procesarEventoClick(evento);
		}
	}

	private void procesarEventoClick(EventObject evento) {
		if (evento.getSource().getClass().getSuperclass().equals(JButton.class)){
			System.out.println("click boton");
			procesarClickBoton(evento);
		}else if (evento.getSource().getClass().equals(JComboBox.class)){
			System.out.println("click combo");
			procesarSeleccionCombo(evento);
		}
	}

	private void procesarSeleccionCombo(EventObject evento) {
		if (evento.getSource().equals(this.frmpago.getCmbtipopago())){
			procesarSeleccionPago();
		}else if (evento.getSource().equals(this.frmpago.getCmbcuenta_pagar())){
			procesarSeleccionCuentaPagar();
		}
	}

	private void procesarSeleccionCuentaPagar() {
		try {
			int cta_seleccionada = this.frmpago.getCmbcuenta_pagar().getSelectedIndex();
			if (cta_seleccionada!=0){
				Cuenta cuenta_seleccionada = empresa.Buscar_Cuentas_NoCerradas_Cliente(cliente).get(cta_seleccionada-1);
				double saldo = cuenta_seleccionada.Calcular_Saldo();
				System.out.println("saldo cuenta: "+saldo);
				if ((saldo<0)&&(this.frmpago.getCmbtipopago().getSelectedItem().toString().toUpperCase().equals(DESCUENTO))){
					JOptionPane.showMessageDialog(frmpago, "Esta cuenta no puede ser pagada por descuento", "SACFRE/Gestionar Pago",JOptionPane.INFORMATION_MESSAGE);
					this.frmpago.getCmbcuenta_pagar().setSelectedIndex(0);
				}else if ((saldo<0)&&(cuenta_seleccionada.getFecha().getMonth()!=(new Date()).getMonth())&&(!this.frmpago.getCmbtipopago().getSelectedItem().toString().toUpperCase().equals(DESCUENTO))){
					JOptionPane.showMessageDialog(frmpago, "Esta cuenta ya expiro! Solo pueden realizarce descuentos sobre ella", "SACFRE/Gestionar Pago",JOptionPane.INFORMATION_MESSAGE);
					this.frmpago.getCmbcuenta_pagar().setSelectedIndex(0);
				}
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	private void procesarClickBoton(EventObject evento) {
		if (evento.getSource().equals(this.frmpago.getBtbuscar())){
			buscarCliente(this.frmpago.getCmbidentificacion().getSelectedItem().toString()+this.frmpago.getTxtnumero().getText());
		}else if (evento.getSource().equals(this.frmpago.getBtregistrar())){
			registrarPago();
		}else if (evento.getSource().equals(this.frmpago.getBtcancelar())){
			cancelar();
		}
	}

	private void procesarSeleccionPago() {
		if (this.frmpago.getCmbtipopago().getSelectedItem().toString().toUpperCase().equals(DESCUENTO)){
			try {
				int cuenta_seleccionada = this.frmpago.getCmbcuenta_pagar().getSelectedIndex();
				if (cuenta_seleccionada!=0){
					Cuenta cuenta = empresa.Buscar_Cuentas_NoCerradas_Cliente(cliente).get(cuenta_seleccionada-1);
					double saldo = cuenta.Calcular_Saldo();
					if (saldo<0){
						JOptionPane.showMessageDialog(frmpago, "La cuenta seleccionada no puede ser pagada con este tipo", "SACFRE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
						this.frmpago.getCmbtipopago().setSelectedIndex(0);
					}else{
						cargarCuentasDescontables();
					}
				}else {
					cargarCuentasDescontables();
				}
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}else {
			this.frmpago.getTbcuentas().LimpiarTabla();
		}
	}

	private void cargarCuentasDescontables() {
		System.out.println(this.frmpago.getCmbidentificacion().getSelectedItem().toString()+this.frmpago.getTxtnumero());
		Cliente cliente = empresa.Buscar_Cliente(this.frmpago.getCmbidentificacion().getSelectedItem().toString()+this.frmpago.getTxtnumero().getText());
		if (cliente==null){
			JOptionPane.showMessageDialog(frmpago, "Debe Buscar Antes un cliente", "SACFRE/Procesar Pago", JOptionPane.INFORMATION_MESSAGE);
		}else{
			List<Cuenta> cuentas = cliente.getCuentas();
			List<Cuenta> descontables = new ArrayList<Cuenta>();
			int size = cuentas.size();
			Cuenta cuenta;
			for (int i=0;i<size;i++){
				cuenta = cuentas.get(i);
				try {
					System.out.println("Saldo Cuenta: "+cuenta.Calcular_Saldo());
					if ((cuenta.Calcular_Saldo()<0)&&(cuenta.getFecha().getMonth()!=(new Date()).getMonth())){
						descontables.add(cuenta);
					}
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}
			size=descontables.size();
			if (size!=0){
				for (int i=0;i<size;i++){
					try {
						cuenta = descontables.get(i);
						String fecha = String.valueOf(cuentas.get(i).getFecha().toGMTString().substring(2, 6).replaceAll(" ", "")+"-"+cuentas.get(i).getFecha().toGMTString().substring(6, 11)).replaceAll(" ", "");
						String fila[] = {cuenta.getId(),fecha,String.valueOf(cuenta.Calcular_Saldo())};
						this.frmpago.getTbcuentas().AgregarFila(fila);
					} catch (ParseException e) {
						e.printStackTrace();
					}
				}
			}else {
				JOptionPane.showMessageDialog(frmpago, "El Cliente no Posee cuentas Descontables", "SACFRE/Procesar Pago", JOptionPane.INFORMATION_MESSAGE);
				this.frmpago.getCmbtipopago().setSelectedIndex(0);
			}
			
		}
	}

	private void cancelar() {
		this.frmpago.getCmbidentificacion().setEnabled(true);
		this.frmpago.getTxtnumero().setEnabled(true);
		this.frmpago.getTbcuentas().LimpiarTabla();
		ActionListener[] escuchador = this.frmpago.getCmbcuenta_pagar().getActionListeners();
		this.frmpago.getCmbcuenta_pagar().removeActionListener(escuchador[0]);
		this.frmpago.getCmbcuenta_pagar().removeAllItems();
		this.frmpago.getCmbcuenta_pagar().addActionListener(escuchador[0]);
		this.frmpago.getBtbuscar().setEnabled(true);
		this.frmpago.getLblapellido2().setText("");
		this.frmpago.getLblnombre2().setText("");
		this.frmpago.getTxtnumero().setText("");
		this.frmpago.getCmbidentificacion().setSelectedIndex(0);
		this.frmpago.getCmbtipopago().setSelectedIndex(0);
		this.frmpago.getTxtconcepto().setText("");
		this.frmpago.getCmbtipopago().setEnabled(false);
		this.frmpago.getCmbcuenta_pagar().setEnabled(false);
		this.frmpago.getTxtmonto().setText("");
		this.cliente=null;
		actualizarMontosDeuda(null);
	}

	private void registrarPago() {
		if (this.cliente==null){
			JOptionPane.showMessageDialog(frmpago, "Debe asociar un cliente al pago", "SACFRE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
		}else if (this.frmpago.getCmbcuenta_pagar().getSelectedIndex()==0){
			JOptionPane.showMessageDialog(frmpago, "Debe seleccionar la cuenta sobre la cual desea realizar el pago", "SACFRE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
		}else if (this.frmpago.getTxtmonto().getText().equals("")){
			JOptionPane.showMessageDialog(frmpago, "Debe indicar el monto del pago", "SACFRE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
		}else if (this.frmpago.getTxtconcepto().getText().equals("")){
			JOptionPane.showMessageDialog(frmpago, "Debe Indicar el concepto del pago", "SACFRE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
		}else if (this.frmpago.getCmbtipopago().getSelectedItem().toString().toUpperCase().equals(DESCUENTO)){
			if (this.frmpago.getTbcuentas().getTabla().getSelectedRowCount()!=1){
				JOptionPane.showMessageDialog(frmpago, "Debe seleccionar una sola cuenta", "SACFE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
			}else{
				double monto_indicado = Double.parseDouble(this.frmpago.getTxtmonto().getText());
				double monto_cuenta_seleccionada = -1*Double.parseDouble((String) this.frmpago.getTbcuentas().getTabla().getValueAt(this.frmpago.getTbcuentas().getTabla().getSelectedRow(), 2));
				if (monto_indicado<=monto_cuenta_seleccionada){
					try {
						if (JOptionPane.showConfirmDialog(frmpago, "¿Esta Seguro de Registrar el Pago?", "SACFRE/Gestionar Pago", JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION){
							//REGISTRANDO PAGO SOBRE CUENTA//
							int numero_pago = empresa.Generar_Numero_Pago();
							Cuenta cuenta = empresa.Buscar_Cuentas_NoCerradas_Cliente(this.cliente).get(this.frmpago.getCmbcuenta_pagar().getSelectedIndex()-1);
							String concepto = this.frmpago.getTxtconcepto().getText();
							Tipo_Pago tipo = empresa.getTipos_Pago().get(this.frmpago.getCmbtipopago().getSelectedIndex());
							Pago pago = new Pago(numero_pago, cuenta, monto_indicado, concepto, new Date(), 'a', tipo);
							Base_DatosDAO conexion = new Base_DatosDAO();
							conexion.save(pago);
							//REGISTRANDO DESCUENTO SOBRE CUENTA//
							numero_pago = empresa.Generar_Numero_Pago();
							concepto = "Pago Sobre Cuenta: "+cuenta.getFecha().toGMTString().substring(2, 10);
							cuenta = empresa.buscarCuenta((String) this.frmpago.getTbcuentas().getTabla().getValueAt(this.frmpago.getTbcuentas().getTabla().getSelectedRow(), 0));
							tipo = empresa.getTipos_Pago().get(this.frmpago.getCmbtipopago().getSelectedIndex());
							Pago pago_inverso = new Pago(numero_pago, cuenta, -1*monto_indicado, concepto, new Date(), 'a', tipo);
							conexion.save(pago_inverso);
							JOptionPane.showMessageDialog(frmpago, "Pago Registrado Exitosamente", "SACFRE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
							cancelar();
						}
					} catch (ParseException e) {
						e.printStackTrace();
					}
				}else{
					JOptionPane.showMessageDialog(frmpago, "El monto indicado es superior al de la cuenta a Descontar", "SACFRE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
				}
			}
		}else if (JOptionPane.showConfirmDialog(frmpago, "¿Esta Seguro de Registrar el Pago?", "SACFRE/Gestionar Pago", JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION){
			try{
				//REGISTRANDO PAGO SOBRE CUENTA//
				double monto_indicado = Double.parseDouble(this.frmpago.getTxtmonto().getText());
				int numero_pago = empresa.Generar_Numero_Pago();
				Cuenta cuenta = empresa.Buscar_Cuentas_NoCerradas_Cliente(this.cliente).get(this.frmpago.getCmbcuenta_pagar().getSelectedIndex()-1);
				String concepto = this.frmpago.getTxtconcepto().getText();
				Tipo_Pago tipo = empresa.getTipos_Pago().get(this.frmpago.getCmbtipopago().getSelectedIndex());
				Pago pago = new Pago(numero_pago, cuenta, monto_indicado, concepto, new Date(), 'a', tipo);
				Base_DatosDAO conexion = new Base_DatosDAO();
				conexion.save(pago);
				JOptionPane.showMessageDialog(frmpago, "Pago Registrado Exitosamente", "SACFRE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
				cancelar();
			}catch (ParseException e) {
				e.printStackTrace();
			}
			
		}
	}

	private void buscarCliente(String identificacion) {
		if (this.frmpago.getTxtnumero().getText().equals("")){
			JOptionPane.showMessageDialog(frmpago, "Debe indicar la id del cliente", "SACFRE/Gestionar Pago", JOptionPane.ERROR_MESSAGE);
		}else {
			Cliente cliente = empresa.Buscar_Cliente(identificacion);
			if (cliente==null){
				JOptionPane.showMessageDialog(frmpago, "El cliente no se encuentra Registrado", "SACFRE/Gestionar Pago", JOptionPane.INFORMATION_MESSAGE);
				cancelar();
			}else{
				cargarCliente(cliente);
				this.frmpago.getCmbtipopago().setEnabled(true);
			}
		}
	}

}
